package com.efast.cafe.portal.service.statemach.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.efast.cafe.commponent.statemach.bean.StateMachTaskHistory;
import com.efast.cafe.commponent.statemach.bean.TaskBean;
import com.efast.cafe.commponent.statemach.dao.PortalStateMachTaskDao;
import com.efast.cafe.commponent.statemach.service.IPortalStateMachTaskHistoryService;
import com.efast.cafe.framework.constant.CommonConstant;
import com.efast.cafe.framework.redis.ObjectRedisTemplate;
import com.efast.cafe.framework.util.SpringWebUtils;
import com.efast.cafe.portal.bean.statemach.PortalStateMachConf;
import com.efast.cafe.portal.bean.statemach.PortalStateMachConfQueryBean;
import com.efast.cafe.portal.bean.statemach.PortalStateMachField;
import com.efast.cafe.portal.bean.statemach.PortalStateMachHandle;
import com.efast.cafe.portal.bean.statemach.PortalStateMachRel;
import com.efast.cafe.portal.bean.statemach.PortalStateMachStateConf;
import com.efast.cafe.portal.bean.statemach.StateMachEntityInfo;
import com.efast.cafe.portal.bean.statemach.StateMachFieldInfo;
import com.efast.cafe.portal.dao.statemach.PortalStateMachConfDao;
import com.efast.cafe.portal.service.statemach.IPortalStateMachConfService;
import com.efast.cafe.portal.service.statemach.IPortalStateMachFieldService;
import com.efast.cafe.portal.service.statemach.IPortalStateMachHandleService;
import com.efast.cafe.portal.service.statemach.IPortalStateMachRelService;
import com.efast.cafe.portal.service.statemach.IPortalStateMachStateService;

@Service
@Transactional
public class PortalStateMachConfServiceImpl implements IPortalStateMachConfService {

	@Autowired
	private PortalStateMachConfDao portalStateMachConfDao;

	@Autowired
	private ObjectRedisTemplate objectRedisTemplate;

	@Autowired
	private IPortalStateMachHandleService portalStateMachHandleService;

	@Autowired
	private IPortalStateMachRelService portalStateMachRelService;

	@Autowired
	private IPortalStateMachStateService portalStateMachStateService;

	@Autowired
	private IPortalStateMachFieldService portalStateMachFieldService;

	@Autowired
	private IPortalStateMachTaskHistoryService portalStateMachTaskHistoryService;

	@Autowired
	private PortalStateMachTaskDao taskDao;

	@Override
	public void insertConf(PortalStateMachConf conf) {
		portalStateMachConfDao.insertConf(conf);
	}

	@Override
	public void updateConf(PortalStateMachConf conf) {
		portalStateMachConfDao.updateConf(conf);
		// 删除缓存
		objectRedisTemplate.delete(CommonConstant.REDIS_STATEMACH_CONFID_ + conf.getId());
	}

	@Override
	public void deleteConf(PortalStateMachConf conf) {
		portalStateMachConfDao.deleteConf(conf);
		// 删除缓存
		objectRedisTemplate.delete(CommonConstant.REDIS_STATEMACH_CONFID_ + conf.getId());
	}

	@Override
	public PortalStateMachConfQueryBean queryPageStateMachConf(PortalStateMachConfQueryBean queryBean) {
		queryBean.setCompanyCode(SpringWebUtils.getRequestCompany());
		queryBean.setResultList(portalStateMachConfDao.queryConfPageList(queryBean));
		queryBean.setTotalRows(portalStateMachConfDao.queryConfPageCount(queryBean));
		return queryBean;
	}

	@Override
	public List<PortalStateMachConf> getConfListByCompanyCode(String companyCode) {
		return portalStateMachConfDao.getConfListByCompanyCode(companyCode);
	}

	@Override
	public void insertConfByMxgraph(PortalStateMachConf conf) {
		conf.setCompanyCode(SpringWebUtils.getRequestCompany());
		Integer maxId = portalStateMachConfDao.getMaxId();
		if(maxId==null || maxId<1000){
			maxId = 1000;
		}else{
			maxId = maxId.intValue()+10;
		}
		conf.setId(maxId.longValue());
		// 创建portal_statemach_conf
		portalStateMachConfDao.insertConf(conf);
		// 解析Mxgraph生成portal_statemach_handle和portal_statemach_rel
		List<PortalStateMachStateConf> confs = analysisMxgraphJSON(conf.getId(), conf.getMxgraph(), true);
		// 添加状态自定义entityDisplay
		analysisField(conf.getId(), conf.getStateEntityInfo(), true, confs);
	}

	@Override
	public void updateConfByMxgraph(PortalStateMachConf conf) {
		// 根据confid删除portal_statemach_handle
		portalStateMachHandleService.deleteHandleByConfId(conf.getId());

		// 根据confid删除portal_statemach_rel
		portalStateMachRelService.deleteRelByConfId(conf.getId());

		// 解析Mxgraph生成portal_statemach_handle和portal_statemach_rel
		List<PortalStateMachStateConf> confs = analysisMxgraphJSON(conf.getId(), conf.getMxgraph(), false);
		// 更新portal_statemach_conf
		portalStateMachConfDao.updateConf(conf);
		// 更新状态自定义entityDisplay
		analysisField(conf.getId(), conf.getStateEntityInfo(), false, confs);
		// 删除缓存
		objectRedisTemplate.delete(CommonConstant.REDIS_STATEMACH_CONFID_ + conf.getId());
	}

	/**
	 * 解析Mxgraph生成portal_statemach_handle和portal_statemach_rel
	 * 
	 * @param confId
	 * @param Mxgraphstr
	 * @param isCreate
	 */
	private List<PortalStateMachStateConf> analysisMxgraphJSON(Long confId, String Mxgraphstr, boolean isCreate) {
		List<PortalStateMachStateConf> ret = new ArrayList<PortalStateMachStateConf>();
		JSONArray mxgraphJSONs = JSONArray.parseArray(Mxgraphstr);
		Set<Long> finishState = new HashSet<Long>();
		for (Iterator<Object> iterator = mxgraphJSONs.iterator(); iterator.hasNext();) {
			JSONObject mxgraphJSON = (JSONObject) iterator.next();
			// 如果是节点且是创建状态
			if (mxgraphJSON.containsKey("vertex") && mxgraphJSON.getBooleanValue("vertex")) {
				// 创建节点和流程的默认配置
				PortalStateMachStateConf psmsc = new PortalStateMachStateConf();
				psmsc.setCompanyCode(SpringWebUtils.getRequestCompany());
				psmsc.setConfId(confId);
				JSONObject valueJSON = mxgraphJSON.getJSONObject("value");
				finishState.add(mxgraphJSON.getLong("id"));
				// 角色先置空再赋值
				psmsc.setExeRole("");
				psmsc.setExeUser("");
				// 获取角色配置和职位配置
				if (valueJSON.containsKey("approvalType")
						&& !StringUtils.isBlank(valueJSON.getString("approvalType"))) {
					String type = valueJSON.getString("approvalType");
					if (type.equals("role")) {
						psmsc.setExeRole(valueJSON.getString("approvalName"));
					} else if (type.equals("user")) {
						psmsc.setExeUser(valueJSON.getString("approvalName"));
					}
				}
				if (valueJSON.containsKey("updateField") && !StringUtils.isBlank(valueJSON.getString("updateField"))) {
					psmsc.setUpdateField(valueJSON.getString("updateField"));
				}
				psmsc.setStateId(valueJSON.getLong("id"));
				psmsc.setViewCode(valueJSON.getString("viewCode"));
				ret.add(psmsc);
				// portalStateMachStateService.insertStateConf(psmsc);
			}
			// 如果是连线
			if (mxgraphJSON.containsKey("edge") && mxgraphJSON.getBooleanValue("edge")) {
				// 添加handle
				PortalStateMachHandle handle = new PortalStateMachHandle();
				JSONObject valueJSON = mxgraphJSON.getJSONObject("value");
				handle.setHandleName(valueJSON.getString("handleName"));
				handle.setHandleUrl(valueJSON.getString("handleURL"));
				handle.setChangeStateId(mxgraphJSON.getLong("targetId"));
				handle.setCompanyCode(SpringWebUtils.getRequestCompany());
				handle.setControllerURL(valueJSON.getString("controllerName"));
				handle.setExeRole(valueJSON.getString("exeRole"));
				handle.setExeUser(valueJSON.getString("exeUser"));
				portalStateMachHandleService.insertHandle(handle);

				// 添加rel
				PortalStateMachRel rel = new PortalStateMachRel();
				rel.setConfId(confId);
				rel.setStateId(mxgraphJSON.getLong("sourceId"));
				rel.setHandleId(handle.getid());
				rel.setCompanyCode(SpringWebUtils.getRequestCompany());
				portalStateMachRelService.insertRel(rel);

				finishState.remove(mxgraphJSON.getLong("sourceId"));
			}
		}
		// 结束节点添加rel，由于结束节点不包含在任何线的sourceId里，所以需要单独处理
		for (Long finishStateId : finishState) {
			PortalStateMachRel rel = new PortalStateMachRel();
			rel.setConfId(confId);
			rel.setStateId(finishStateId);
			rel.setHandleId(0L);
			rel.setCompanyCode(SpringWebUtils.getRequestCompany());
			portalStateMachRelService.insertRel(rel);
		}
		return ret;
	}

	/**
	 * 状态自定义entityDisplay
	 * 
	 * @param confId
	 * @param stateEntityInfos
	 * @param isCreate
	 */
	private void analysisField(Long confId, List<StateMachEntityInfo> stateEntityInfos, boolean isCreate,
			List<PortalStateMachStateConf> stateConfs) {
		if (!isCreate) {
			portalStateMachFieldService.delFieldByConfig(confId);
		}
		List<PortalStateMachField> insertFields = new ArrayList<PortalStateMachField>();
		for (StateMachEntityInfo sei : stateEntityInfos) {
			for (int i = 0; i < stateConfs.size(); i++) {
				if(stateConfs.get(i)!=null && stateConfs.get(i).getStateId()!=null && sei!=null && sei.getStateId()!=null){
					if (stateConfs.get(i).getStateId().equals(sei.getStateId())
							&& (sei.getObjName()!=null && !sei.getObjName().equals("portal_statemach_task"))) {
						stateConfs.get(i).setExtForm(sei.getObjName());
					}
				}
			}
			if(null!=sei.getFieldInfo()){
				for (StateMachFieldInfo fi : sei.getFieldInfo()) {
					PortalStateMachField psmf = new PortalStateMachField();
					psmf.setConfId(confId);
					psmf.setStateId(sei.getStateId());
					psmf.setObjId(sei.getObjId());
					psmf.setFieldId(fi.getFieldId());
					psmf.setDisplay(fi.getDisplay());
					psmf.setViewCode(sei.getViewCode());
					psmf.setCompanyCode(SpringWebUtils.getRequestCompany());
					insertFields.add(psmf);
				}
			}
			
		}
		// 插入更新stateconf
		for (PortalStateMachStateConf stateConf : stateConfs) {
			portalStateMachStateService.replaceStateConf(stateConf);
		}
		if (insertFields.size() > 0) {
			portalStateMachFieldService.insertStateMachFields(insertFields);
		}
	}

	/**
	 * 根据ID获取conf
	 */
	@Override
	public PortalStateMachConf getConfById(Long id) {
		PortalStateMachConf ret = new PortalStateMachConf();
		ret = portalStateMachConfDao.getConfById(id);
		ret.setStateEntityInfo(getStateMachEntityInfoByConfId(id));
		return ret;
	}

	/**
	 * 根据taskID获取conf
	 */
	@Override
	public PortalStateMachConf getConfBytaskId(Long taskId) {
		PortalStateMachConf ret = new PortalStateMachConf();
		// 根据taskId获取task主数据
		TaskBean taskBean = taskDao.getTaskById(SpringWebUtils.getRequestCompany(), taskId);
		if (taskBean != null) {
			ret = portalStateMachConfDao.getConfById(taskBean.getConfId());
			List<StateMachTaskHistory> ths = portalStateMachTaskHistoryService.queryTaskHistoryByTaskId(taskId);
			Long[][] retths = new Long[ths.size()][2];
			for (int i = 0; i < ths.size(); i++) {
				retths[i][0] = ths.get(i).getStateId();
				retths[i][1] = ths.get(i).getChangeState();
			}
			ret.setTaskHistory(retths);
		}
		return ret;
	}

	/**
	 * EntityDisplay对象转换
	 * 
	 * @param id
	 * @return
	 */
	private List<StateMachEntityInfo> getStateMachEntityInfoByConfId(Long id) {
		List<StateMachEntityInfo> ret = new ArrayList<StateMachEntityInfo>();

		// 根据流程id获取EntityDisplay配置
		List<PortalStateMachField> insertFields = portalStateMachFieldService.getStateMachFieldByConfig(id);

		Long oldsumid = 0l;
		StateMachEntityInfo smei = null;
		List<StateMachFieldInfo> smfis = new ArrayList<StateMachFieldInfo>();
		for (PortalStateMachField psmf : insertFields) {
			if (oldsumid == 0) {
				oldsumid = psmf.getStateId() + psmf.getObjId();
				smei = new StateMachEntityInfo();
				smei.setStateId(psmf.getStateId());
				smei.setObjId(psmf.getObjId());
				smei.setLabel(psmf.getFieldName());
				smei.setObjName(psmf.getObjName());
				smei.setViewCode(psmf.getViewCode());
			} else {
				if (!oldsumid.equals(psmf.getStateId() + psmf.getObjId())) {
					smei.setFieldInfo(smfis);
					ret.add(smei);
					smfis = new ArrayList<StateMachFieldInfo>();
					oldsumid = psmf.getStateId() + psmf.getObjId();
					smei = new StateMachEntityInfo();
					smei.setStateId(psmf.getStateId());
					smei.setObjId(psmf.getObjId());
					smei.setLabel(psmf.getFieldName());
					smei.setObjName(psmf.getObjName());
					smei.setViewCode(psmf.getViewCode());
				}
			}
			StateMachFieldInfo smfi = new StateMachFieldInfo();
			if (!StringUtils.isBlank(psmf.getDisplay())) {
				smfi.setFieldId(psmf.getFieldId());
				smfi.setDisplay(psmf.getDisplay());
				smfis.add(smfi);
			}
		}
		if(smfis!=null && !smfis.isEmpty())
			smei.setFieldInfo(smfis);
		if(smei!=null)
			ret.add(smei);
		return ret;
	}
}
